import { Controller, Get, Param, Query, Res } from '@nestjs/common';
import { Response } from 'express';
import { PrismaService } from 'src/modules/prisma.service';
import { LogType } from 'monitor-sdk';
import { MonitorService } from './monitor.service';
import { PerformanceInsertZod } from 'src/types/entrity/Performance.dto';
import { z } from 'zod';
import { PerformanceZod } from 'src/types/dto';
import { PerformanceVoZod } from 'src/types/vo/Performance.dto.vo';
import { safeParse } from 'src/utils';
import { CodeErrorAddZod } from 'src/types/dtoExt/CodeError.dto';
import { CodeErrorVo, CodeErrorVoZod } from 'src/types/vo/CodeError.vo';
import { ApiPaginationResponse, Pagination } from 'src/decorator/swagger';

@Controller('/')
export class MonitorController {
  constructor(
    private readonly mysql: PrismaService,
    private readonly monitorService: MonitorService,
  ) {}

  /**
   * 日志收集接口
   */
  @Get(['/:timestamp.gif'])
  async log(
    @Param('timestamp') timestamp: string,
    @Query() query: BaseObj<string>,
    @Res() res: Response
  ) {
    const logType: LogType = +query.__lt;
    if (logType === LogType.BaseInfo) {
      const data: z.infer<typeof PerformanceInsertZod> = {
        account: query.account,
        tabFlag: query.__tf,
        fingerPrint: query.__fp,
        projectFlag: +query.__pv,
        logType: +query.__lt,
        FP: +query.FP,
        FCP: +query.FCP,
        deviceName: query.dn,
        deviceVersion: query.dv,
        browser: query.b,
        browserVersion: query.bv,
      }
      PerformanceInsertZod.safeParseAsync(data).then(res => {
        if (res.success) {
          this.monitorService.savePerformance(res.data);
        } else {
          console.warn('>>> 数据不符合条件,', res.error);
        }
      });
    } else if (logType > 100 && logType < 200) {
      /**
       * 保存js报错日志
       */
      const data: z.infer<typeof CodeErrorAddZod> = {
        account: query.account,
        tabFlag: query.__tf,
        fingerPrint: query.__fp,
        projectFlag: +query.__pv,
        logType: +query.__lt,
        browserUrl: query.bu,
        message: query.msg,
      }
      this.monitorService.saveCodeError(safeParse(CodeErrorAddZod, data));
    } else if (logType > 200 && logType < 300) {
      // TODO，处理请求报错
    } else if (logType > 300 && logType < 400) {
      // TODO，处理校验报错
    }


    /**
     * 清除多余的响应头
     * 以下无法在send之前清除
     * Etag
     * Content-Length
     * Content-Type
     */
    res.removeHeader('Date');
    res.removeHeader('Keep-Alive');
    res.removeHeader('X-Powered-By');
    res.removeHeader('Connection');
    res.removeHeader('Transfer-Encoding');
    res.removeHeader('Access-Control-Allow-Credentials');
    res.removeHeader('Access-Control-Allow-Origin');
    
    res.type('gif').send(
      Buffer.from(
        'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
        'base64',
      ),
    );
  }

  /**
   * 获取统计信息
   */
  @Get('/log/performance')
  async getPerformance() {
    const list = await this.mysql.performance.findMany();
    return safeParse(z.array(PerformanceVoZod), list);
  }

  /**
   * 分页获取js报错日志
   */
  @Get('/log/codeError')
  @ApiPaginationResponse(CodeErrorVo, { desc: '分页获取js报错日志' })
  async getCodeError(@Query() query: Pagination) {
    const list = await this.mysql.codeError.findMany({
      take: Number(query.pageSize || 10),
      skip: (Number(query.currentPage || 1) - 1 ) * Number(query.pageSize || 10),
      orderBy: [
        {
          updateTime: 'desc',
        }
      ]
    });
    const totalCount = await this.mysql.codeError.count();

    const messageList = await this.mysql.errorMessage.findMany({
      where: {
        id: { in: list.map(item => item.messageId) }
      }
    })
    list.forEach(item => (item as any).message = messageList.find(messageItem => messageItem.id ===item.messageId)?.message);
    return {
      list: safeParse(z.array(CodeErrorVoZod), list),
      pageSize: Number(query.pageSize || 10),
      currentPage: Number(query.currentPage || 1),
      totalCount,
    };
  }
}
